home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / lz13.zip / LZDCMP3.ASM < prev    next >
Assembly Source File  |  1993-05-01  |  7KB  |  277 lines

  1.     title    lzdcmp - file decompressor using limpel-ziev algorithm
  2.  
  3. ;Tom Pfau
  4. ;Digital Equipment Corporation
  5. ;Parsippany, NJ
  6. ;
  7. ;v1.2 - Toad Hall Tweak
  8. ; - converting to .COM file
  9. ; - uses tweaked MACROS2.MLB
  10. ; - Takes input file from command line, outputs to StdOut
  11. ; - Added some file error halts (sorry, no msgs yet)
  12. ; - Bumped i/o buffers to 4Kb from original 1Kb
  13.  
  14. ;Constants
  15. CLEAR        equ    256
  16. EOF        equ    257
  17. FIRST_FREE    equ    258
  18. BUFFSIZE    equ    4096        ;TH
  19.  
  20.     include    macros2.mlb
  21.  
  22. ;Hash table entry
  23. hash_rec    struc
  24. next    dw    ?            ; prefix code
  25. char    db    ?            ; suffix char
  26. hash_rec    ends
  27.  
  28. ;Start coding
  29. code    segment para public 'code'
  30.     assume    CS:code,DS:code, ES:code    ;TH
  31.     org    100H            ;TH
  32.  
  33. LzDcmp2    proc    near
  34.     jmp    Start            ;TH
  35.  
  36. input_handle    dw    0        ;TH default to StdIn
  37. cur_code    dw    0    ;?
  38. old_code    dw    0    ;?
  39. in_code        dw    0    ;?
  40. free_code    dw    FIRST_FREE
  41. stack_count    dw    0
  42. nbits        dw    9
  43. max_code    dw    512
  44. fin_char    db    0    ;?
  45. k        db    0    ;?
  46. masks        dw    1ffh,3ffh,7ffh,0fffh
  47. bit_offset    dw    0
  48. output_offset    dw    0
  49. LzDcmp2    endp
  50.  
  51.  
  52. start    proc    near
  53.     mov    si,80H                ;point to PSP cmd line
  54.     lodsb                    ;snarf cmd line len byte
  55.     or    al,al                ;anything on cmd line?
  56.     jz    Start_Process            ;nope, use < stdin
  57.  
  58.     xor    ah,ah                ;clear msb
  59. ;SI now points to 81H
  60.     mov    dx,si                ;not quite first char
  61.     inc    dx                ;DX points to target filename
  62.     add    si,ax                ;point to beyond last char
  63.     mov    [si],ah                ;make file name AsciiZ
  64.     mov    ax,3D00H            ;open file/device
  65.     int    21H
  66.     jb    Terminate            ;failed somehow, die
  67.  
  68.     mov    input_handle,ax            ;save input handle
  69.  
  70. Start_Process:
  71.     call    decompress        ;Decompress files
  72. Terminate:                ;TH errorlevel in AL
  73. ;TH Note:  I don't bother closing any files .. the 4CH terminate
  74. ;seems to let DOS do it nicely.  Never had any problems yet
  75. ;with running out of handles, etc.
  76.  
  77.     mov    ah,4CH            ;TH terminate process
  78.     int    21H
  79. start    endp
  80.  
  81. decompress    proc    near
  82.     hread    input_handle,input_buffer,BUFFSIZE    ;TH Read from input
  83.     jb    Terminate        ;TH failed somehow
  84.  
  85. l1:    call    read_code        ;Get a code
  86.     cmp    ax,EOF            ;End of file?
  87.     jne    l2            ;no
  88.  
  89.     mov    ax,output_offset    ;TH output buffer offset
  90.     or    ax,ax            ;TH Data in output buffer?
  91.     je    l1a            ;no (TH return Errorlevel 0)
  92.      mov    dx,offset output_buffer    ;TH buffer to write from
  93.      mov    cx,ax            ;TH nr bytes to write
  94.      mov    bx,1            ;TH StdOut
  95.      mov    ah,40H            ;TH write to file/dev
  96.      int    21H            ;flush buffer
  97. l1a:    ret                ;done
  98.  
  99. l2:    cmp    ax,CLEAR        ;Clear code?
  100.     jne    l7            ;no
  101.  
  102.     call    init_tab        ;Initialize table
  103.     call    read_code        ;Read next code
  104.     mov    cur_code,ax        ;Initialize variables
  105.     mov    old_code,ax
  106.     mov    k,al
  107.     mov    fin_char,al
  108.     call    write_char        ;Write character
  109.     jmp    l1            ;Get next code
  110.  
  111. l7:    mov    cur_code,ax        ;Save new code
  112.     mov    in_code,ax
  113.     cmp    ax,free_code        ;Code in table? (k<w>k<w>k)
  114.     jl    l11            ;yes
  115.      mov    ax,old_code        ;get previous code
  116.      mov    cur_code,ax        ;make current
  117.      mov    al,fin_char        ;get old last char
  118.      push    ax            ;push it
  119.      inc    stack_count
  120.      mov    ax,cur_code        ;TH sigh ...
  121. l11:
  122. ;TH AX should have cur_code in any case
  123. ;    cmp    cur_code,255        ;Code or character?
  124.     cmp    ax,255            ;TH Code or character?
  125.     jle    l15            ;Char
  126.  
  127. ;     mov    bx,cur_code        ;Convert code to address
  128.      mov    bx,ax            ;TH Convert code to address
  129.      call    index
  130.      mov    al,2[bx]        ;Get suffix char
  131.      push    ax            ;push it
  132.      inc    stack_count
  133.      mov    ax,[bx]            ;Get prefix code
  134.      mov    cur_code,ax        ;Save it
  135.      jmp    l11            ;Translate again
  136.  
  137. l15:
  138. ;TH ax should still have cur_code
  139. ;    mov    ax,cur_code        ;Get code
  140.     mov    fin_char,al        ;Save as final, k
  141.     mov    k,al
  142.     push    ax            ;Push it
  143.     inc    stack_count
  144.     mov    cx,stack_count        ;Pop stack
  145.     jcxz    l18            ;If anything there
  146. l17:     pop    ax
  147.      call    write_char
  148.      loop    l17
  149. l18:    mov    stack_count,cx        ;Clear count on stack
  150.     call    add_code        ;Add new code to table
  151.     mov    ax,in_code        ;Save input code
  152.     mov    old_code,ax
  153.     mov    bx,free_code        ;Hit table limit?
  154.     cmp    bx,max_code
  155.     jl    l23            ;Less means no
  156.      cmp    nbits,12        ;Still within twelve bits?
  157.      je    l23            ;no (next code should be clear)
  158.       inc    nbits            ;Increase code size
  159.       shl    max_code,1        ;Double max code
  160. l23:    jmp    l1            ;Get next code
  161. decompress    endp    
  162.  
  163. read_code    proc    near
  164.     mov    ax,bit_offset        ;Get bit offset
  165.     add    ax,nbits        ;Adjust by code size
  166.     xchg    bit_offset,ax        ;Swap
  167.     mov    cx,8            ;Calculate byte offset
  168.     xor    dx,dx
  169.     div    cx
  170. ;    cmp    ax,1021            ;Approaching end of buffer?
  171.     cmp    ax,BUFFSIZE-3        ;TH approaching end of buffer?
  172.     jl    rd0            ;no
  173.  
  174.     push    dx            ;Save offset in byte
  175.     add    dx,nbits        ;Calculate new bit offset
  176.     mov    bit_offset,dx
  177. ;    mov    cx,1024            ;1k buffer
  178.     mov    cx,BUFFSIZE        ;TH 4Kb buffer
  179.     mov    bp,ax            ;save byte offset
  180.     sub    cx,ax            ;Calculate bytes left
  181.     mov    di,offset input_buffer    ;TH Point to beginning of buffer
  182.     add    ax,di            ;TH Point to char
  183.  
  184.     mov    si,ax
  185. rep    movsb                ;Move last chars down
  186. ;TH I broke the macro!
  187. ;    hread    input_handle,[di],bp    ;Fill rest of buffer
  188.     mov    dx,di            ;TH DI points to next empty space
  189.     mov    cx,bp            ;TH bytes to write
  190.     mov    bx,input_handle        ;TH read handle
  191.     mov    ah,3FH            ;TH read from file/device
  192.     int    21H
  193.     jb    File_Error        ;TH file error
  194.  
  195.     xor    ax,ax            ;Clear ax
  196.     pop    dx            ;Restore offset in byte
  197. rd0:    add    ax,offset input_buffer    ;Point to char
  198.     mov    si,ax
  199.     lodsw                ;Get word
  200.     mov    bx,ax            ;Save in AX
  201.     lodsb                ;Next byte
  202.     mov    cx,dx            ;Offset in byte
  203.     jcxz    rd2            ;If zero, skip shifts
  204. rd1:     shr    al,1            ;Put code in low (code size) bits of BX
  205.      rcr    bx,1
  206.      loop    rd1
  207. rd2:    mov    ax,bx            ;put code in ax
  208.     mov    bx,nbits        ;mask off unwanted bits
  209.     sub    bx,9
  210.     shl    bx,1
  211.     and    ax,masks[bx]
  212.     ret
  213.  
  214. File_Error:                ;TH jmp here with errorcode in AL
  215.     jmp    Terminate        ;TH Die
  216. read_code    endp
  217.  
  218. init_tab    proc    near
  219.     mov    nbits,9            ;Initialize variables
  220.     mov    max_code,512
  221.     mov    free_code,FIRST_FREE
  222.     ret
  223. init_tab    endp
  224.  
  225. write_char    proc    near
  226.     mov    di,output_offset    ;Get offset in buffer
  227. ;    cmp    di,1024            ;Full?
  228.     cmp    di,BUFFSIZE        ;TH Full?
  229.     jl    wc1            ;no
  230.      push    ax            ;Save registers
  231.      push    cx
  232.      mov    dx,offset output_buffer    ;TH buffer to write
  233.      mov    cx,di            ;TH nr bytes to write
  234.      mov    bx,1            ;TH StdOut
  235.      mov    ah,40H            ;TH write to file/dev
  236.      int    21H            ;write buffer to file
  237.      jb    File_Error        ;TH failed somehow
  238.  
  239.      pop    cx
  240.      pop    ax
  241.      xor    di,di    ;TH        ;Point to beginning of buffer
  242.      mov    output_offset,di
  243. wc1:
  244. ;    lea    di,output_buffer[di]    ;Point into buffer
  245.     add    di,offset output_buffer    ;TH
  246.     stosb                ;Store char
  247.     inc    output_offset        ;Increment number of chars in buffer
  248.     ret
  249. write_char    endp
  250.  
  251. index        proc    near
  252.     mov    bp,bx            ;bx = bx * 3 (3 byte entries)
  253.     shl    bx,1            ;bp = bx
  254.     add    bx,bp            ;bx = bx * 2 + bp
  255.     add    bx,offset hash        ;TH add in hashtable base offset
  256.     ret
  257. index        endp
  258.  
  259. add_code    proc    near
  260.     mov    bx,free_code        ;Get new code
  261.     call    index            ;convert to address
  262.     mov    al,k            ;get suffix char
  263.     mov    [bx].char,al        ;save it
  264.     mov    ax,old_code        ;get prefix code
  265.     mov    [bx].next,ax        ;save it
  266.     inc    free_code        ;set next code
  267.     ret
  268. add_code    endp
  269.  
  270. input_buffer    equ    $            ;db    1024 dup (?)
  271. output_buffer    equ    input_buffer+BUFFSIZE    ;db    1024 dup (?)
  272. hash        equ    output_buffer+BUFFSIZE
  273.  
  274. code    ends
  275.  
  276.     end    LzDcmp2
  277.